export default {
  id: 'tag-pair',
  description: '标签必须成对出现',
  init(parser, reporter) {
    const stack = []

    parser.addListener('tagstart', (event) => {
      const tagName = event.tagName
      if (!event.close) {
        stack.push({
          tagName: tagName,
          line: event.line,
          raw: event.raw,
        })
      }
    })

    parser.addListener('tagend', (event) => {
      const tagName = event.tagName

      // Look up the matching start tag
      let pos
      for (pos = stack.length - 1; pos >= 0; pos--) {
        if (stack[pos].tagName === tagName) {
          break
        }
      }

      if (pos >= 0) {
        const arrTags = []
        for (let i = stack.length - 1; i > pos; i--) {
          arrTags.push(`</${stack[i].tagName}>`)
        }

        if (arrTags.length > 0) {
          const lastEvent = stack[stack.length - 1]
          reporter.error(
            `标签没有成对出现, 丢失: [ ${arrTags.join(
              ''
            )} ], 在第 ${
              lastEvent.line
            }行，起始标签匹配失败[ ${lastEvent.raw} ]`,
            event.line,
            event.col,
            this,
            event.raw
          )
        }
        stack.length = pos
      } else {
        reporter.error(
          `标签必须成对出现, 没有起始标签: [ ${event.raw} ]`,
          event.line,
          event.col,
          this,
          event.raw
        )
      }
    })

    parser.addListener('end', (event) => {
      const arrTags = []

      for (let i = stack.length - 1; i >= 0; i--) {
        arrTags.push(`</${stack[i].tagName}>`)
      }

      if (arrTags.length > 0) {
        const lastEvent = stack[stack.length - 1]
        reporter.error(
          `标签必须成对出现, 丢失: [ ${arrTags.join(
            ''
          )} ], [ ${lastEvent.raw} ] 在第 ${
            lastEvent.line
          }行，标签匹配失败`,
          event.line,
          event.col,
          this,
          ''
        )
      }
    })
  },
}
